package com.example.demoweb.interceptor;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Iterator;
import java.util.List;
import java.util.Set;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.apache.commons.codec.binary.Hex;
import org.springframework.stereotype.Component;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;
import com.example.demoweb.util.StringUtils;
import com.google.gson.Gson;
import com.google.gson.JsonObject;

@Component
public class RequestInterceptor2 implements HandlerInterceptor{

	@Override
	public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
			throws Exception {
		//从流中获取http的body信息
		BufferedReader br = request.getReader();
		String inputLine;
	    StringBuffer sb = new StringBuffer();
	     try {
	       while ((inputLine = br.readLine()) != null) {
	    	   sb.append(inputLine);
	       }
	       br.close();
	     } catch (IOException e) {
	       System.out.println("IOException: " + e);
	     }
		Gson gson = new Gson();
		String encryptStr = "";
		String signStr = "";
		if(sb.length()>0) {
			//将body信息全部转成object
			JsonObject streamDataJo = gson.fromJson(sb.toString(),JsonObject.class);
			//从object中获取header、body、sign
			JsonObject headerJo = streamDataJo.get("header").getAsJsonObject();
			JsonObject bodyJo = streamDataJo.get("body").getAsJsonObject();
			signStr = streamDataJo.get("sign").toString();
			//获取header的所有key
			Set headerSet = headerJo.keySet();
			//对header中所有的key进行排序，返回排序完成之后所对应的value值
			String headerStr = mySort(headerSet,headerJo);
			//获取body的所有key
			Set bodySet = bodyJo.keySet();
			//对body中所有的key进行排序，返回排序完成之后所对应的value值
			String bodyStr = mySort(bodySet,bodyJo);
			//排序后的header的value字符串和body的value字符串进行拼接
			String combineStr = headerStr + "," + bodyStr; 
			//md5加密
			encryptStr = encrypt(combineStr);
			
			System.out.println(combineStr);
			System.out.println(encryptStr);
			
		}
		//如果加密后的结果与前台传过来的加密后的结构一致则请求通过，如果不一致则不通过
		if(StringUtils.isNotBlank(encryptStr) &&  (encryptStr == signStr || encryptStr.equals(signStr))) {
			System.out.println(">>>MyInterceptor1>>>>>>>在请求处理之前进行调用（Controller方法调用之前）");
			return true;
		}else {
			return false;// 只有返回true才会继续向下执行，返回false取消当前请求
		}
	}

	public static String beanToJSONString(Object bean) {
	    return new Gson().toJson(bean);
	}
	
	@Override
	public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler,
			ModelAndView modelAndView) throws Exception {
		 System.out.println(">>>MyInterceptor1>>>>>>>请求处理之后进行调用，但是在视图被渲染之前（Controller方法调用之后）");
		
	}

	@Override
	public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex)
			throws Exception {
		System.out.println(">>>MyInterceptor1>>>>>>>在整个请求结束之后被调用，也就是在DispatcherServlet 渲染了对应的视图之后执行（主要是用于进行资源清理工作）");
	}
	
	/**
	 * 排序
	 * @param set
	 * @param jo
	 * @return
	 */
	private String mySort(Set set,JsonObject jo) {
		List<String> list = new ArrayList<String>();
		list.addAll(set);
		//对list中的值进行排序，list中的值为header或body的key键
		Collections.sort(list);
		Iterator headerIt = list.iterator();
		StringBuffer sb = new StringBuffer();
		//根据排序完成后的key键的顺序去取对应的value值并拼接成字符串
		while(headerIt.hasNext()) {
			sb.append(jo.get(headerIt.next().toString())+",");
		}
		String resultStr = sb.substring(0, sb.length()-1);
		return resultStr;
	}
	/**
	 * md5加密
	 * @param str
	 * @return
	 * @throws UnsupportedEncodingException
	 */
	private String encrypt(String str) throws UnsupportedEncodingException {
		String resultStr = "";
		try {
			MessageDigest md5 = MessageDigest.getInstance("MD5");
			byte[] newStr=md5.digest(str.getBytes("utf-8"));
		    //加密后的字符串
			resultStr = Hex.encodeHexString(newStr);
		} catch (NoSuchAlgorithmException e) {
			e.printStackTrace();
		}
		return resultStr;
	}
}